package org.light4admin.modules.system.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.light4admin.common.Constants;
import org.light4admin.common.base.BusinessException;
import org.light4admin.modules.system.contract.req.SysLoginReq;
import org.light4admin.modules.system.domain.SysLogininfor;
import org.light4admin.modules.system.domain.SysUser;
import org.light4admin.modules.system.domain.vo.LoginUser;
import org.light4admin.modules.system.mapper.SysUserMapper;
import org.light4admin.modules.system.service.ISysLogininforService;
import org.light4admin.modules.system.service.ISysPermissionService;
import org.light4admin.modules.system.utils.SecurityUtils;
import org.light4admin.util.IpUtils;
import org.light4admin.util.ServletUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.Set;

/**
 * 登录校验方法
 *
 * @author light4admin
 */
@Slf4j
@Component
public class SysLoginService {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private ISysPermissionService permissionService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private ISysLogininforService logininforService;
    @Value("${verify.enabled:true}")
    private boolean verifyEnabled;

    /**
     * 登录
     */
    public LoginUser login(SysLoginReq req) {
        // 校验
        String uuid = req.getUuid();
        String code = req.getCode();
        checkVerifyCode(uuid, code);

        String username = req.getUsername();
        String password = req.getPassword();

        SysUser user = sysUserMapper.selectUserByUserName(username);
        if (Objects.isNull(user)) {
            insertLog(false, "登录用户不存在");
            throw new BusinessException("登录用户不存在");
        }

        if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
            insertLog(false, "用户不存在/密码错误");
            throw new BusinessException("用户不存在/密码错误");
        }

        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user.getUserId());
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user.getUserId());
        LoginUser sysUserVo = new LoginUser();
        sysUserVo.setSysUser(user);
        sysUserVo.setRoles(roles);
        sysUserVo.setPermissions(permissions);

        insertLog(true, "登录成功");
        return sysUserVo;
    }


    @Async
    public void insertLog(Boolean loginSuccess, String message) {
        String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
        SysLogininfor logininfor = new SysLogininfor();
        logininfor.setUserName(SecurityUtils.getUsername());
        logininfor.setIpaddr(ip);
        logininfor.setMsg(message);
        // 日志状态
        if (loginSuccess) {
            logininfor.setStatus("1");
        } else {
            logininfor.setStatus("0");
        }
        logininforService.insertLogininfor(logininfor);
    }


    private void checkVerifyCode(String uuid, String code) {
        if (!verifyEnabled) {
            log.warn("【验证码暂不开启】");
            return;
        }

        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
        String captcha = redisService.getCacheObject(verifyKey);
        redisService.deleteObject(verifyKey);
        if (captcha == null) {
            throw new BusinessException("验证码已失效");
        }
        if (!code.equalsIgnoreCase(captcha)) {
            throw new BusinessException("验证码不正确");
        }
    }

}
